package util

import (
	"gitchina/smartguard-api/errors"
)

const (
	NOTIFY_CATEGORY_LOAD  = "NOTIFY_CATEGORY_LOAD"
	NOTIFY_ATTRIBUTE_LOAD = "NOTIFY_ATTRIBUTE_LOAD"
)

var pipe chan Event
var registion *SafeMap

type Event struct {
	Name string
	Data interface{}
}

type RegistionNode struct {
	fn     func(data interface{}) errors.Error
	failed func(err errors.Error)
	next   *RegistionNode
	tail   *RegistionNode
}

func init() {
	go start()
}

func start() {
	pipe = make(chan Event, 200)
	registion = NewSafeMap()
	for {
		dispatch(<-pipe)
	}
}

func (e Event) Pub() {
	pipe <- e
}

func Sub(name string) *RegistionNode {
	n := &RegistionNode{}
	if val, ok := registion.Get(name); ok {
		if node := val.(*RegistionNode); node.next == nil {
			node.next = n
			node.tail = n
		} else {
			node.tail.next = n
			node.tail = n
		}
	} else {
		registion.Set(name, n)
	}
	return n
}

func (n *RegistionNode) On(fn func(data interface{}) errors.Error) *RegistionNode {
	n.fn = fn
	return n
}

func (n *RegistionNode) Failed(fn func(err errors.Error)) {
	n.failed = fn
}

func dispatch(e Event) {
	if val, ok := registion.Get(e.Name); ok {
		for n := val.(*RegistionNode); n != nil; n = n.next {
			if err := n.fn(e.Data); err != nil {
				n.failed(err)
			}
		}
	}
}
